package fun.flyee.android.pengshan.utils;

import android.content.Context;
import android.location.LocationManager;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.maps.model.LatLng;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import fun.flyee.android.pengshan.AppContex;

public class GeoUtil {

    public static boolean isPolygonContainsPoint(List<LatLng> var0, LatLng var1) {
        if (var0 != null && var0.size() != 0 && var1 != null) {
            int var2;
            for (var2 = 0; var2 < var0.size(); ++var2) {
                if (var1.longitude == ((LatLng) var0.get(var2)).longitude && var1.latitude == ((LatLng) var0.get(var2)).latitude) {
                    return true;
                }
            }
            var2 = 0;
            boolean var3 = false;
            LatLng var4 = null;
            LatLng var5 = null;
            double var6 = 0.0D;
            int var8 = var0.size();
            for (int var9 = 0; var9 < var8; ++var9) {
                var4 = (LatLng) var0.get(var9);
                var5 = (LatLng) var0.get((var9 + 1) % var8);
                if (var4.latitude != var5.latitude && var1.latitude >= Math.min(var4.latitude, var5.latitude) && var1.latitude <= Math.max(var4.latitude, var5.latitude)) {
                    var6 = (var1.latitude - var4.latitude) * (var5.longitude - var4.longitude) / (var5.latitude - var4.latitude) + var4.longitude;
                    if (var6 == var1.longitude) {
                        return true;
                    }
                    if (var6 < var1.longitude) {
                        ++var2;
                    }
                }
            }

            return var2 % 2 == 1;
        } else {
            return false;
        }
    }

    public static AMapLocationClient getLocation(LocationCallback locationCallback) {
        try {
            List<AMapLocation> points = new ArrayList<>();
            AMapLocationClient mClient = new AMapLocationClient(AppContex.getContext());
            AMapLocationClientOption mOption = new AMapLocationClientOption();
            mOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
            mOption.setInterval(3000);
            mClient.setLocationOption(mOption);
            mClient.setLocationListener((loc) -> {
                points.add(loc);
                if(points.size()>5){
                    points.remove(0);
                }
                LatLng latLng = getRealPosition(points);
                if (locationCallback != null) {
                    locationCallback.callback(latLng.latitude, latLng.longitude);
                }
            });
            mClient.startLocation();
            return mClient;
        } catch (Exception e) {
            Logger.e("location error", e);
            return null;
        }
    }

    public static AMapLocationClient getTrace(TraceCallback traceCallback) {
        try {
            AMapLocationClient mClient = new AMapLocationClient(AppContex.getContext());
            AMapLocationClientOption mOption = new AMapLocationClientOption();
            mOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
            mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
//            mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
            mOption.setInterval(5000);
            mClient.setLocationOption(mOption);
            mClient.setLocationListener((loc) -> {
                if (traceCallback != null) {
                    traceCallback.callback(loc);
                }
            });
            mClient.startLocation();
            return mClient;
        } catch (Exception e) {
            Logger.e("location error", e);
            return null;
        }
    }

    public static LatLng getRealPosition(List<AMapLocation> locs) {
        if (locs.size() == 0) return null;
        if (locs.size() == 1) {
            return new LatLng(locs.get(0).getLatitude(), locs.get(0).getLongitude());
        }
        List<Position> poss = new ArrayList<>();
        for (int i = 0; i < locs.size(); i++) {
            Position pos = new Position(i, locs.get(i));
            if (locs.size() > 3) {
                for (int j = 0; j < locs.size(); j++) {
                    if (i == j) continue;
                    pos.factor += pos.loc.distanceTo(locs.get(j));
                }
            }
            poss.add(pos);
        }
        if (poss.size() > 3) {
            Collections.sort(poss, (p1, p2) -> p1.factor > p2.factor ? 1 : -1);
            poss = poss.subList(0, poss.size() / 2);
        }
        double totalLat = 0, totalLng = 0;
        int count = 0;
        for (Position pos : poss) {
            totalLat += pos.loc.getLatitude();
            totalLng += pos.loc.getLongitude();
            count++;
        }
        LatLng point = new LatLng(totalLat / count, totalLng / count);
        return point;
    }

    public static LatLng getRealPositionSimple(List<AMapLocation> locs) {
        if (locs.size() == 0) return null;
        if (locs.size() == 1) {
            return new LatLng(locs.get(0).getLatitude(), locs.get(0).getLongitude());
        }
        List<Position> poss = new ArrayList<>();
        for (int i = 0; i < locs.size(); i++) {
            Position pos = new Position(i, locs.get(i));
            poss.add(pos);
        }
        double totalLat = 0, totalLng = 0;
        int count = 0;
        for (Position pos : poss) {
            totalLat += pos.loc.getLatitude();
            totalLng += pos.loc.getLongitude();
            count++;
        }
        LatLng point = new LatLng(totalLat / count, totalLng / count);
        return point;
    }

    public static class Position {
        int index;
        AMapLocation loc;
        double factor = 0d;

        public Position(int index, AMapLocation loc) {
            this.index = index;
            this.loc = loc;
        }
    }

    public interface LocationCallback {
        void callback(Double lat, Double lng);
    }

    public interface TraceCallback {
        void callback(AMapLocation loc);
    }

}
